<template>
  <div class="article-detail">
    <a-spin :spinning="loading" size="large">
      <div v-if="article" class="article-wrapper">
        <!-- 文章主体内容 -->
        <article class="article-main">
          <!-- 文章头部 -->
          <header class="article-header">
            <h1 class="article-title">{{ article.title }}</h1>
            <div class="author-card-meta">
              <time class="author-card-time">{{ formatRelativeTime(article.created_at) }}</time>
              <span class="author-card-views"><eye-outlined /> {{ formatNumber(article.view_count || 0) }} 阅读</span>
              <div class="article-meta only-stats">
                <div class="article-stats">
                  <span class="stat-item">
                    <like-outlined :class="{ active: article.is_liked }" />
                    {{ formatNumber(article.like_count || 0) }}
                  </span>
                  <span class="stat-item">
                    <message-outlined />
                    {{ formatNumber(article.comment_count || 0) }}
                  </span>
                  <span class="stat-item">
                    <star-outlined :class="{ active: article.is_favorited }" />
                    {{ formatNumber(article.favorite_count || 0) }}
                  </span>
                </div>
              </div>
            </div>

            <!-- 标签 -->
            <div v-if="article.tags?.length" class="article-tags">
              <a-tag v-for="tag in article.tags" :key="tag" class="tag-item">
                {{ tag }}
              </a-tag>
            </div>
          </header>

          <!-- 文章内容 -->
          <div class="article-content">
            <div v-if="article.cover_image" class="cover-image">
              <img :src="getImageUrl(article.cover_image)" :alt="article.title" />
            </div>
            <div class="content-body">
              <md-preview :modelValue="processedContent" :theme="'light'" autoFoldThreshold="3000" @onGetCatalog="handleGetCatalog" :previewOnly="true" />
            </div>
          </div>

          <!-- 文章底部操作区 -->
          <div class="article-footer">
            <div class="action-buttons">
              <a-button size="large" :type="article.is_liked ? 'primary' : 'default'" :loading="likeLoading" @click="handleLike" :icon="h(LikeOutlined)" class="action-btn like-btn" :class="{ active: article.is_liked }">
                点赞 {{ formatNumber(article.like_count || 0) }}
              </a-button>

              <a-button size="large" :type="article.is_favorited ? 'primary' : 'default'" :loading="favoriteLoading" @click="handleFavorite" :icon="h(StarOutlined)" class="action-btn favorite-btn" :class="{ active: article.is_favorited }">
                收藏 {{ formatNumber(article.favorite_count || 0) }}
              </a-button>

              <a-button size="large" @click="handleShare" :icon="h(ShareAltOutlined)" class="action-btn share-btn"> 分享 </a-button>
            </div>
          </div>

          <!-- 评论区 -->
          <div class="comments-section">
            <div class="comments-header">
              <h3>评论 ({{ article.comment_count || 0 }})</h3>
            </div>

            <!-- 发表评论 -->
            <div v-if="userStore.isAuthenticated" class="comment-form">
              <div class="comment-form-header">
                <a-avatar :size="32" class="user-avatar" :src="userStore.avatar ? getImageUrl(userStore.avatar) : ''" :style="{ cursor: 'pointer', fontSize: '14px' }">
                  {{ userStore.user?.username?.charAt(0) || 'U' }}
                </a-avatar>
                <span class="username">{{ userStore.user?.username }}</span>
              </div>
              <a-textarea v-model:value="newComment" placeholder="写下你的评论..." :rows="4" :max-length="1000" show-count class="comment-textarea" />
              <div class="comment-form-actions">
                <a-button type="primary" @click="handleSubmitComment" :loading="commentSubmitting" :disabled="!newComment.trim()" size="large"> 发表评论 </a-button>
              </div>
            </div>
            <div v-else class="login-tip">
              <a-alert message="请登录后发表评论" type="info" show-icon>
                <template #action>
                  <a-button size="small" type="primary" @click="handleLogin"> 登录 </a-button>
                </template>
              </a-alert>
            </div>

            <!-- 评论列表 -->
            <div class="comments-list">
              <a-spin :spinning="commentsLoading">
                <div v-if="comments.length === 0 && !commentsLoading" class="no-comments">
                  <a-empty description="暂无评论，快来发表第一条评论吧！" />
                </div>
                <div v-else>
                  <div v-for="comment in comments" :key="comment.id" class="comment-item">
                    <div class="comment-avatar" @click="handleCommentUserClick(comment.user_id)">
                      <a-avatar :src="comment.user_avatar ? getImageUrl(comment.user_avatar) : ''" :style="{ cursor: 'pointer', fontSize: '16px' }">
                        {{ comment.user_name?.charAt(0) || 'U' }}
                      </a-avatar>
                    </div>
                    <div class="comment-content">
                      <div class="comment-header">
                        <span class="comment-author">{{ comment.user_name }}</span>
                        <span class="comment-time">{{ formatRelativeTime(comment.created_at) }}</span>
                      </div>
                      <div class="comment-text">{{ comment.content }}</div>
                      <div class="comment-actions">
                        <a-button type="text" size="small" :class="{ liked: comment.is_liked }" @click="handleCommentLike(comment)">
                          <like-outlined />
                          {{ comment.like_count || 0 }}
                        </a-button>
                        <a-button type="text" size="small" @click="handleReply(comment)"> 回复 </a-button>
                        <a-button v-if="canDeleteComment(comment)" type="text" size="small" danger @click="handleDeleteComment(comment)" :loading="comment.deleting"> 删除 </a-button>
                      </div>

                      <!-- 回复列表 -->
                      <div v-if="comment.replies?.length" class="replies-list">
                        <div v-for="reply in comment.replies" :key="reply.id" class="reply-item">
                          <div class="reply-avatar" @click="handleCommentUserClick(reply.user_id)">
                            <a-avatar size="small" :src="reply.user_avatar ? getImageUrl(reply.user_avatar) : ''" :style="{ cursor: 'pointer', fontSize: '12px' }">
                              {{ reply.user_name?.charAt(0) || 'U' }}
                            </a-avatar>
                          </div>
                          <div class="reply-content">
                            <div class="reply-header">
                              <span class="reply-author">{{ reply.user_name }}</span>
                              <span class="reply-time">{{ formatRelativeTime(reply.created_at) }}</span>
                            </div>
                            <div class="reply-text">{{ reply.content }}</div>
                            <div class="reply-actions">
                              <a-button type="text" size="small" :class="{ liked: reply.is_liked }" @click="handleCommentLike(reply)">
                                <like-outlined />
                                {{ reply.like_count || 0 }}
                              </a-button>
                              <a-button type="text" size="small" @click="handleReplyToReply(reply, comment.id)"> 回复 </a-button>
                              <a-button v-if="canDeleteComment(reply)" type="text" size="small" danger @click="handleDeleteComment(reply)" :loading="reply.deleting"> 删除 </a-button>
                            </div>

                            <!-- 回复的回复表单 -->
                            <div v-if="replyingTo === reply.id" class="reply-form">
                              <a-textarea v-model:value="replyContent" :placeholder="`回复 @${reply.user_name}`" :rows="3" :max-length="500" show-count />
                              <div class="reply-form-actions">
                                <a-button size="small" @click="cancelReply">取消</a-button>
                                <a-button type="primary" size="small" @click="handleSubmitReply()" :loading="replySubmitting" :disabled="!replyContent.trim()"> 回复 </a-button>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>

                      <!-- 回复表单 -->
                      <div v-if="replyingTo === comment.id" class="reply-form">
                        <a-textarea v-model:value="replyContent" :placeholder="`回复 @${comment.user_name}`" :rows="3" :max-length="500" show-count />
                        <div class="reply-form-actions">
                          <a-button size="small" @click="cancelReply">取消</a-button>
                          <a-button type="primary" size="small" @click="handleSubmitReply()" :loading="replySubmitting" :disabled="!replyContent.trim()"> 回复 </a-button>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </a-spin>

              <!-- 加载更多评论 -->
              <div v-if="commentsPagination.hasNext" class="load-more-comments">
                <a-button @click="loadMoreComments" :loading="loadingMoreComments" size="large" block> 加载更多评论 </a-button>
              </div>
            </div>
          </div>
        </article>

        <!-- 固定操作栏（左侧） -->
        <div class="left-action-bar" :style="leftActionBarStyle">
          <div class="action-group">
            <div class="action-item" :class="{ active: article.is_liked }" @click="handleLike" title="点赞">
              <like-outlined />
              <span class="count">{{ formatNumber(article.like_count || 0) }}</span>
            </div>

            <div class="action-item" :class="{ active: article.is_favorited }" @click="handleFavorite" title="收藏">
              <star-outlined />
              <span class="count">{{ formatNumber(article.favorite_count || 0) }}</span>
            </div>

            <div class="action-item" @click="scrollToComments" title="评论">
              <message-outlined />
              <span class="count">{{ formatNumber(article.comment_count || 0) }}</span>
            </div>

            <div class="action-item" @click="handleShare" title="分享">
              <share-alt-outlined />
            </div>
          </div>

          <!-- 编辑删除按钮 -->
          <div v-if="isAuthor" class="author-actions-sidebar">
            <a-button type="text" @click="handleEdit"> <edit-outlined /> 编辑 </a-button>
            <a-button type="text" danger @click="handleDelete"> <delete-outlined /> 删除 </a-button>
          </div>
        </div>

        <!-- 侧边栏 -->
        <aside class="article-sidebar">
          <!-- 作者信息卡片（右侧上方） -->
          <div v-if="article" class="author-card">
            <div class="author-card-header">
              <a-avatar :size="48" class="author-card-avatar" @click="handleAuthorClick" :src="article.author_avatar ? getImageUrl(article.author_avatar) : ''" :style="{ fontSize: '28px' }">
                {{ article.author_name?.charAt(0) || 'A' }}
              </a-avatar>
              <div class="author-card-info">
                <div class="author-card-name" @click="handleAuthorClick">{{ article.author_name }}</div>
                <div class="author-card-stats">
                  <span class="stat-item">
                    <file-text-outlined />
                    {{ authorStats.articleCount || 0 }} 篇文章
                  </span>
                  <span class="author-card-stats">
                    <eye-outlined />
                    {{ formatNumber(authorStats.totalViews || 0) }} 总阅读
                  </span>
                </div>
              </div>
            </div>
            <div class="author-card-actions">
              <a-button type="primary" @click="handleAuthorClick" :icon="h(UserOutlined)"> 查看主页 </a-button>
              <a-button
                v-if="userStore.isAuthenticated && article.author_id !== userStore.user?.userId"
                :type="authorFollowStatus.isFollowing ? 'default' : 'primary'"
                :loading="authorFollowStatus.loading"
                @click="handleFollowAuthor"
                :icon="h(authorFollowStatus.isFollowing ? UserDeleteOutlined : UserAddOutlined)"
              >
                {{ authorFollowStatus.isFollowing ? '已关注' : '关注' }}
              </a-button>
            </div>
          </div>

          <!-- 文章目录 -->
          <div v-if="articleCatalog.length > 0" class="article-catalog">
            <div class="catalog-header">
              <h4><unordered-list-outlined /> 文章目录</h4>
            </div>
            <div class="catalog-list">
              <div v-for="(item, index) in articleCatalog" :key="index" :class="['catalog-item', `level-${item.level}`]" @click="handleCatalogClick(item.text)">
                <span class="catalog-text">{{ item.text }}</span>
              </div>
            </div>
          </div>
        </aside>
      </div>

      <!-- 文章不存在 -->
      <div v-else-if="!loading" class="article-not-found">
        <a-result status="404" title="文章不存在" sub-title="抱歉，你访问的文章可能已被删除或不存在">
          <template #extra>
            <a-button type="primary" @click="$router.push('/articles')"> 返回文章列表 </a-button>
          </template>
        </a-result>
      </div>
    </a-spin>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, computed, h, nextTick, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { message, Modal } from 'ant-design-vue'
import { EyeOutlined, LikeOutlined, MessageOutlined, StarOutlined, EditOutlined, DeleteOutlined, ShareAltOutlined, FileTextOutlined, UserOutlined, UserAddOutlined, UserDeleteOutlined, UnorderedListOutlined } from '@ant-design/icons-vue'
import { MdPreview } from 'md-editor-v3'
import 'md-editor-v3/lib/preview.css'
import { useUserStore } from '@/stores/user'
import { getToken } from '@/utils/auth'
import { getImageUrl } from '@/utils/image'
import { formatRelativeTime } from '@/utils/time'
import { API_BASE_URL } from '@/utils/api'

const route = useRoute()
const router = useRouter()
const userStore = useUserStore()

// 响应式数据
const loading = ref(false)
const article = ref(null)
const originalTitle = ref(document.title) // 保存原始标题
const comments = ref([])
const commentsLoading = ref(false)
const commentsPagination = ref({
  page: 1,
  limit: 20,
  total: 0,
  hasNext: false
})
const loadingMoreComments = ref(false)

// 交互状态
const likeLoading = ref(false)
const favoriteLoading = ref(false)
const commentSubmitting = ref(false)
const replySubmitting = ref(false)

// 表单数据
const newComment = ref('')
const replyingTo = ref(null)
const replyContent = ref('')
const replyTargetId = ref(null) // 存储到数据库的 parentId
const replyNotifyTargetId = ref(null) // 需要通知的用户的评论ID

// 作者相关数据
const authorStats = ref({
  articleCount: 0,
  totalViews: 0,
  totalLikes: 0
})
const authorFollowStatus = ref({
  isFollowing: false,
  loading: false
})

// 文章目录数据
const articleCatalog = ref([])

// 左侧固定操作栏位置样式，动态计算使其贴着文章内容左侧
const leftActionBarStyle = ref({ left: '0px' })

const updateLeftActionBarPosition = () => {
  try {
    const articleMainEl = document.querySelector('.article-main')
    if (articleMainEl) {
      const rect = articleMainEl.getBoundingClientRect()
      // 使用 viewport 左偏移，配合 transform: translateX(-100% - gap) 实现“贴着文章内容”
      leftActionBarStyle.value = { left: `${Math.round(rect.left) - 110}px` }
    }
  } catch (e) {}
}

// 计算属性
const isAuthor = computed(() => {
  return userStore.isAuthenticated && article.value && (userStore.user.userId === article.value.author_id || userStore.user.username === 'woaichitudouo')
})

// 处理后的文章内容 - 处理图片地址
const processedContent = computed(() => {
  if (!article.value?.content) return ''

  // 使用正则表达式处理 Markdown 中的图片地址
  return article.value.content.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (match, alt, src) => {
    // 如果图片地址不是完整的 URL，则使用 getImageUrl 处理
    let processedSrc = src
    if (!src.startsWith('http://') && !src.startsWith('https://') && !src.startsWith('data:')) {
      processedSrc = getImageUrl(src)
    }
    return `![${alt}](${processedSrc})`
  })
})

// 获取文章详情
const fetchArticleDetail = async () => {
  loading.value = true

  try {
    const headers = {}
    const token = getToken()
    if (token) {
      headers.Authorization = `Bearer ${token}`
    }

    const response = await fetch(`${API_BASE_URL}/articles/${route.params.id}`, { headers })
    const result = await response.json()

    if (result.code === 200) {
      article.value = result.data
      // 设置页面标题
      document.title = `${article.value.title} - 文章详情`

      // 获取作者相关信息
      if (article.value.author_id) {
        fetchAuthorStats(article.value.author_id)
        if (userStore.isAuthenticated) {
          fetchAuthorFollowStatus(article.value.author_id)
        }
      }
    } else {
      message.error(result.msg || '获取文章详情失败')
    }
  } catch (error) {
    console.error('获取文章详情失败:', error)
    message.error('网络错误，请稍后重试')
  } finally {
    loading.value = false
  }
}

// 获取作者统计数据
const fetchAuthorStats = async (authorId) => {
  try {
    const response = await fetch(`${API_BASE_URL}/articles/user/${authorId}/stats`)
    const result = await response.json()

    if (result.code === 200) {
      authorStats.value = {
        articleCount: result.data.articleCount || 0,
        totalViews: result.data.totalViews || 0,
        totalLikes: result.data.totalLikes || 0
      }
    }
  } catch (error) {
    console.error('获取作者统计失败:', error)
  }
}

// 获取作者关注状态
const fetchAuthorFollowStatus = async (authorId) => {
  try {
    const response = await fetch(`${API_BASE_URL}/follows/check/${authorId}`, {
      headers: {
        Authorization: `Bearer ${getToken()}`
      }
    })
    const result = await response.json()

    if (result.code === 200) {
      authorFollowStatus.value.isFollowing = result.data.isFollowing
    }
  } catch (error) {
    console.error('获取关注状态失败:', error)
  }
}

// 获取评论列表
const fetchComments = async (page = 1, append = false) => {
  if (page === 1) {
    commentsLoading.value = true
  } else {
    loadingMoreComments.value = true
  }

  try {
    const headers = {}
    const token = getToken()
    if (token) {
      headers.Authorization = `Bearer ${token}`
    }

    const response = await fetch(`${API_BASE_URL}/articles/${route.params.id}/comments?page=${page}&limit=${commentsPagination.value.limit}`, { headers })
    const result = await response.json()

    if (result.code === 200) {
      if (append) {
        comments.value.push(...result.data.list)
      } else {
        comments.value = result.data.list || []
      }
      commentsPagination.value = {
        ...commentsPagination.value,
        ...result.data.pagination
      }
    } else {
      message.error(result.msg || '获取评论失败')
    }
  } catch (error) {
    console.error('获取评论失败:', error)
    message.error('网络错误，请稍后重试')
  } finally {
    commentsLoading.value = false
    loadingMoreComments.value = false
  }
}

// 处理点赞
const handleLike = async () => {
  if (!userStore.isAuthenticated) {
    message.info('请先登录')
    handleLogin()
    return
  }

  likeLoading.value = true

  try {
    const response = await fetch(`${API_BASE_URL}/articles/${route.params.id}/like`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${getToken()}`
      }
    })
    const result = await response.json()

    if (result.code === 200) {
      article.value.is_liked = result.data.is_liked
      if (result.data.is_liked) {
        article.value.like_count = (article.value.like_count || 0) + 1
        message.success('点赞成功')
      } else {
        article.value.like_count = Math.max(0, (article.value.like_count || 0) - 1)
        message.success('取消点赞')
      }
    } else {
      message.error(result.msg || '操作失败')
    }
  } catch (error) {
    console.error('点赞失败:', error)
    message.error('网络错误，请稍后重试')
  } finally {
    likeLoading.value = false
  }
}

// 处理收藏
const handleFavorite = async () => {
  if (!userStore.isAuthenticated) {
    message.info('请先登录')
    handleLogin()
    return
  }

  favoriteLoading.value = true

  try {
    const response = await fetch(`${API_BASE_URL}/articles/${route.params.id}/favorite`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${getToken()}`
      }
    })
    const result = await response.json()

    if (result.code === 200) {
      article.value.is_favorited = result.data.is_favorited
      if (result.data.is_favorited) {
        article.value.favorite_count = (article.value.favorite_count || 0) + 1
        message.success('收藏成功')
      } else {
        article.value.favorite_count = Math.max(0, (article.value.favorite_count || 0) - 1)
        message.success('取消收藏')
      }
    } else {
      message.error(result.msg || '操作失败')
    }
  } catch (error) {
    console.error('收藏失败:', error)
    message.error('网络错误，请稍后重试')
  } finally {
    favoriteLoading.value = false
  }
}

// 发表评论
const handleSubmitComment = async () => {
  if (!newComment.value.trim()) {
    message.warning('请输入评论内容')
    return
  }

  commentSubmitting.value = true

  try {
    const response = await fetch(`${API_BASE_URL}/articles/${route.params.id}/comments`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${getToken()}`
      },
      body: JSON.stringify({
        content: newComment.value.trim()
      })
    })
    const result = await response.json()

    if (result.code === 200) {
      newComment.value = ''
      message.success('评论成功')
      // 刷新评论列表
      fetchComments(1)
      // 更新文章评论数
      if (article.value) {
        article.value.comment_count = (article.value.comment_count || 0) + 1
      }
    } else {
      message.error(result.msg || '评论失败')
    }
  } catch (error) {
    console.error('评论失败:', error)
    message.error('网络错误，请稍后重试')
  } finally {
    commentSubmitting.value = false
  }
}

// 处理评论点赞
const handleCommentLike = async (comment) => {
  if (!userStore.isAuthenticated) {
    message.info('请先登录')
    handleLogin()
    return
  }

  try {
    const response = await fetch(`${API_BASE_URL}/articles/comments/${comment.id}/like`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${getToken()}`
      }
    })
    const result = await response.json()

    if (result.code === 200) {
      comment.is_liked = result.data.is_liked
      if (result.data.is_liked) {
        comment.like_count = (comment.like_count || 0) + 1
      } else {
        comment.like_count = Math.max(0, (comment.like_count || 0) - 1)
      }
    } else {
      message.error(result.msg || '操作失败')
    }
  } catch (error) {
    console.error('评论点赞失败:', error)
    message.error('网络错误，请稍后重试')
  }
}

// 处理回复
const handleReply = (comment) => {
  if (!userStore.isAuthenticated) {
    message.info('请先登录')
    handleLogin()
    return
  }

  replyingTo.value = comment.id
  replyTargetId.value = comment.id // 回复根评论时，两者相同
  replyNotifyTargetId.value = comment.id // 通知根评论作者
  replyContent.value = ''
}

// 处理对回复的回复
const handleReplyToReply = (reply, rootCommentId) => {
  if (!userStore.isAuthenticated) {
    message.info('请先登录')
    handleLogin()
    return
  }

  // 回复表单显示在被点击的回复下面
  replyingTo.value = reply.id

  // 对于数据结构的考虑：
  // - 如果要保持两级结构，parentId 应该指向根评论
  // - 如果要支持多级结构，parentId 应该指向直接父级
  // 这里我们保持两级结构，所以 parentId 指向根评论
  replyTargetId.value = rootCommentId // 指向根评论ID，保持两级结构
  replyNotifyTargetId.value = reply.id // 通知被回复的用户
  replyContent.value = `@${reply.user_name} `
}

// 取消回复
const cancelReply = () => {
  replyingTo.value = null
  replyTargetId.value = null
  replyNotifyTargetId.value = null
  replyContent.value = ''
}

// 提交回复
const handleSubmitReply = async () => {
  if (!replyContent.value.trim()) {
    message.warning('请输入回复内容')
    return
  }

  replySubmitting.value = true

  try {
    const response = await fetch(`${API_BASE_URL}/articles/${route.params.id}/comments`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${getToken()}`
      },
      body: JSON.stringify({
        content: replyContent.value.trim(),
        parentId: replyTargetId.value,
        notifyTargetId: replyNotifyTargetId.value
      })
    })
    const result = await response.json()

    if (result.code === 200) {
      replyContent.value = ''
      replyingTo.value = null
      replyTargetId.value = null
      replyNotifyTargetId.value = null
      message.success('回复成功')
      // 刷新评论列表
      fetchComments(1)
      // 更新文章评论数
      if (article.value) {
        article.value.comment_count = (article.value.comment_count || 0) + 1
      }
    } else {
      message.error(result.msg || '回复失败')
    }
  } catch (error) {
    console.error('回复失败:', error)
    message.error('网络错误，请稍后重试')
  } finally {
    replySubmitting.value = false
  }
}

// 加载更多评论
const loadMoreComments = () => {
  fetchComments(commentsPagination.value.page + 1, true)
}

// 编辑文章
const handleEdit = () => {
  router.push(`/articles/edit/${route.params.id}`)
}

// 删除文章
const handleDelete = () => {
  Modal.confirm({
    title: '确认删除',
    content: '确定要删除这篇文章吗？删除后不可恢复。',
    okText: '确定',
    cancelText: '取消',
    okType: 'danger',
    onOk: async () => {
      try {
        const response = await fetch(`${API_BASE_URL}/articles/${route.params.id}`, {
          method: 'DELETE',
          headers: {
            Authorization: `Bearer ${getToken()}`
          }
        })
        const result = await response.json()

        if (result.code === 200) {
          message.success('文章已删除')
          router.push('/articles')
        } else {
          message.error(result.msg || '删除失败')
        }
      } catch (error) {
        console.error('删除文章失败:', error)
        message.error('网络错误，请稍后重试')
      }
    }
  })
}

// 分享文章
const handleShare = async () => {
  const url = window.location.href
  const title = article.value?.title || '文章分享'

  if (navigator.share) {
    try {
      await navigator.share({
        title: title,
        url: url
      })
    } catch (error) {
      console.log('分享取消或失败:', error)
    }
  } else {
    // 复制链接到剪贴板
    try {
      await navigator.clipboard.writeText(url)
      message.success('链接已复制到剪贴板')
    } catch (error) {
      console.error('复制失败:', error)
      message.error('复制失败，请手动复制链接')
    }
  }
}

// 跳转到作者页面
const handleAuthorClick = () => {
  if (article.value?.author_id) {
    router.push(`/user/${article.value.author_id}`)
  }
}

// 跳转到评论用户页面
const handleCommentUserClick = (userId) => {
  if (userId) {
    router.push(`/user/${userId}`)
  }
}

// 关注/取消关注作者
const handleFollowAuthor = async () => {
  if (!userStore.isAuthenticated) {
    message.info('请先登录')
    handleLogin()
    return
  }

  if (!article.value?.author_id) return

  authorFollowStatus.value.loading = true

  try {
    const endpoint = authorFollowStatus.value.isFollowing ? `${API_BASE_URL}/follows/unfollow/${article.value.author_id}` : `${API_BASE_URL}/follows/follow/${article.value.author_id}`

    const response = await fetch(endpoint, {
      method: authorFollowStatus.value.isFollowing ? 'DELETE' : 'POST',
      headers: {
        Authorization: `Bearer ${getToken()}`
      }
    })
    const result = await response.json()

    if (result.code === 200) {
      authorFollowStatus.value.isFollowing = !authorFollowStatus.value.isFollowing
      message.success(authorFollowStatus.value.isFollowing ? '关注成功' : '取消关注成功')
    } else {
      message.error(result.msg || '操作失败')
    }
  } catch (error) {
    console.error('关注操作失败:', error)
    message.error('网络错误，请稍后重试')
  } finally {
    authorFollowStatus.value.loading = false
  }
}

// 检查是否可以删除评论
const canDeleteComment = (comment) => {
  if (!userStore.isAuthenticated) return false

  // 评论作者可以删除自己的评论
  const isCommentAuthor = comment.user_id === userStore.user?.userId

  // 文章作者可以删除文章的任何评论
  const isArticleAuthor = article.value && userStore.user?.userId === article.value.author_id

  // 管理员可以删除任何评论
  const isAdmin = userStore.user?.username === 'woaichitudouo'

  return isCommentAuthor || isArticleAuthor || isAdmin
}

// 删除评论
const handleDeleteComment = (comment) => {
  Modal.confirm({
    title: '确认删除',
    content: '确定要删除这条评论吗？删除后不可恢复。',
    okText: '确定',
    cancelText: '取消',
    okType: 'danger',
    onOk: async () => {
      // 设置删除状态 - 使用 Vue 3 的响应式更新
      if (!comment.hasOwnProperty('deleting')) {
        comment.deleting = false
      }
      comment.deleting = true

      try {
        const response = await fetch(`${API_BASE_URL}/articles/comments/${comment.id}`, {
          method: 'DELETE',
          headers: {
            Authorization: `Bearer ${getToken()}`
          }
        })
        const result = await response.json()

        if (result.code === 200) {
          message.success('评论已删除')
          // 刷新评论列表
          fetchComments(1)
          // 更新文章评论数
          if (article.value) {
            article.value.comment_count = Math.max(0, (article.value.comment_count || 0) - 1)
          }
        } else {
          message.error(result.msg || '删除失败')
        }
      } catch (error) {
        console.error('删除评论失败:', error)
        message.error('网络错误，请稍后重试')
      } finally {
        comment.deleting = false
      }
    }
  })
}

// 处理登录
const handleLogin = () => {
  window.dispatchEvent(new CustomEvent('openLogin'))
}

// 格式化数字
const formatNumber = (num) => {
  if (!num) return '0'
  if (num < 1000) return num.toString()
  if (num < 10000) return (num / 1000).toFixed(1) + 'k'
  return (num / 10000).toFixed(1) + 'w'
}

// 滚动到评论区
const scrollToComments = () => {
  const commentsElement = document.querySelector('.comments-section')
  if (commentsElement) {
    commentsElement.scrollIntoView({ behavior: 'smooth' })
  }
}

// 处理目录获取
const handleGetCatalog = (list) => {
  // 存储目录数据用于侧边栏显示
  articleCatalog.value = list || []

  // 调试信息：显示每个目录项的详细信息
  if (list && list.length > 0) {
    list.forEach((item, index) => {})
  }
}

// 处理目录点击跳转
const handleCatalogClick = (clickedText) => {
  // 防重复点击
  if (handleCatalogClick.clicking) {
    return
  }
  handleCatalogClick.clicking = true

  nextTick(() => {
    // 查找文章内容区域的所有标题
    const allHeadings = document.querySelectorAll('.content-body h1, .content-body h2, .content-body h3, .content-body h4, .content-body h5, .content-body h6, .md-preview h1, .md-preview h2, .md-preview h3, .md-preview h4, .md-preview h5, .md-preview h6')

    // 遍历所有标题，找到文字完全匹配的
    let targetElement = null
    Array.from(allHeadings).forEach((heading) => {
      const headingText = heading.textContent.trim()

      if (headingText === clickedText.trim()) {
        targetElement = heading
      }
    })

    if (targetElement) {
      // 获取滚动容器
      const scrollContainer = document.querySelector('.article-detail')

      if (scrollContainer) {
        // 计算滚动位置
        const containerRect = scrollContainer.getBoundingClientRect()
        const elementRect = targetElement.getBoundingClientRect()
        const currentScrollTop = scrollContainer.scrollTop

        const targetScrollTop = Math.max(0, elementRect.top - containerRect.top + currentScrollTop - 100)

        // 清除之前的高亮
        allHeadings.forEach((h) => {
          h.style.backgroundColor = ''
          h.style.color = ''
          h.style.borderLeft = ''
          h.style.paddingLeft = ''
          h.style.borderRadius = ''
          h.style.boxShadow = ''
        })

        // 滚动
        scrollContainer.scrollTo({
          top: targetScrollTop,
          behavior: 'smooth'
        })

        // 高亮显示
        targetElement.style.transition = 'all 0.5s ease'
        targetElement.style.backgroundColor = '#ff4757'
        targetElement.style.color = 'white'
        targetElement.style.borderLeft = '6px solid #ff3742'
        targetElement.style.paddingLeft = '15px'
        targetElement.style.borderRadius = '4px'
        targetElement.style.boxShadow = '0 2px 10px rgba(255, 71, 87, 0.3)'

        // 3秒后恢复
        setTimeout(() => {
          if (targetElement.style) {
            targetElement.style.backgroundColor = ''
            targetElement.style.color = ''
            targetElement.style.borderLeft = ''
            targetElement.style.paddingLeft = ''
            targetElement.style.borderRadius = ''
            targetElement.style.boxShadow = ''
          }
        }, 3000)
      } else {
        // 备用滚动方式
        targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' })
      }
    }

    // 重置点击状态
    setTimeout(() => {
      handleCatalogClick.clicking = false
    }, 300)
  })
}

handleCatalogClick.clicking = false

// 页面加载时获取数据
onMounted(() => {
  fetchArticleDetail()
  fetchComments()
  // 监听窗口变化，保持贴边
  window.addEventListener('resize', updateLeftActionBarPosition)
  window.addEventListener('scroll', updateLeftActionBarPosition, { passive: true })
})

// 监听文章数据变化，重新计算位置
watch(
  article,
  () => {
    if (article.value) {
      // 等待DOM更新完成后计算位置
      nextTick(() => {
        setTimeout(() => {
          updateLeftActionBarPosition()
        }, 100) // 给一点延迟确保内容完全渲染
      })
    }
  },
  { immediate: true }
)

// 组件销毁前恢复原始标题
onBeforeUnmount(() => {
  document.title = originalTitle.value
  window.removeEventListener('resize', updateLeftActionBarPosition)
  window.removeEventListener('scroll', updateLeftActionBarPosition)
})
</script>

<style scoped>
.article-detail {
  background: #f5f7fa;
  height: 100%;
  overflow-y: auto;
  padding: 20px 0;
}

.article-wrapper {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  gap: 24px;
  align-items: flex-start;
}

.article-main {
  flex: 1;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
}

.article-header {
  padding: 32px 32px 24px;
  border-bottom: 1px solid #f0f0f0;
  background: linear-gradient(135deg, #fff 0%, #fafbfc 100%);
  position: relative;
}

.article-header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
}

.article-title {
  font-size: 36px;
  font-weight: 800;
  line-height: 1.3;
  margin: 0 0 24px 0;
  word-break: break-word;
  background-clip: text;
}

.article-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-left: 30px;
}

.article-meta.only-stats {
  justify-content: flex-end;
}

.author-section {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  border-radius: 25px;
  background: linear-gradient(135deg, #f7f9fe 0%, #e8f3ff 100%);
  border: 1px solid #e8f3ff;
  box-shadow: 0 2px 8px rgba(30, 128, 255, 0.1);
}

.author-avatar {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

.author-avatar:hover {
  transform: scale(1.1) rotate(5deg);
  box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
}

.author-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.author-name {
  font-size: 14px;
  font-weight: 600;
  color: #1d2129;
  cursor: pointer;
  transition: all 0.3s ease;
}

.author-name:hover {
  color: #667eea;
  transform: translateX(2px);
}

.meta-info {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #8a919f;
}

.separator {
  margin: 0 4px;
  color: #d9d9d9;
}

.meta-info .anticon,
.view-count .anticon {
  font-size: 12px;
  /* 移除强制颜色设置，保持图标原有颜色 */
}

.view-count .anticon {
  margin-right: 6px;
}

.publish-time {
  color: #8a919f;
  font-weight: 500;
}

/* 作者信息浮层 */
.author-popover {
  width: 280px;
}

.author-popover-header {
  display: flex;
  align-items: center;
  gap: 16px;
}

.author-avatar-lg {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  box-shadow: 0 6px 16px rgba(102, 126, 234, 0.3);
}

.author-popover-info {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.popover-name {
  font-weight: 700;
  color: #1d2129;
  font-size: 16px;
}

.popover-meta {
  font-size: 13px;
  color: #8a919f;
}

.author-popover-actions {
  margin-top: 16px;
  text-align: right;
}

.article-stats {
  display: flex;
  align-items: center;
  gap: 20px;
}

.stat-item {
  display: flex;
  align-items: center;
  gap: 6px;
  color: #8a919f;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.3s ease;
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(248, 249, 250, 0.8);
}

.article-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}

.tag-item {
  border: 1px solid #e4e6ea;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  color: #495057;
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 8px;
  margin: 0;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  font-weight: 500;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.tag-item:hover {
  background: linear-gradient(135deg, #e8f3ff 0%, #d1e9ff 100%);
  border-color: #667eea;
  color: #667eea;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
}

.article-content {
  padding: 32px;
}

.cover-image {
  text-align: center;
  margin-bottom: 32px;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

.cover-image img {
  max-width: 100%;
  height: auto;
  border-radius: 16px;
  transition: transform 0.3s ease;
}

.content-body {
  font-size: 16px;
  line-height: 1.8;
  color: #2c3e50;
  word-break: break-word;
}

/* md-preview 组件样式 */
.content-body :deep(.md-preview) {
  background: transparent;
  padding: 0;
}

.content-body :deep(.md-preview-wrapper) {
  background: transparent;
  padding: 0;
}

/* 掘金风格的文章内容样式 */
.content-body :deep(h1),
.content-body :deep(h2),
.content-body :deep(h3),
.content-body :deep(h4),
.content-body :deep(h5),
.content-body :deep(h6) {
  margin: 40px 0 20px 0;
  font-weight: 700;
  line-height: 1.4;
  color: #1a1a1a;
  position: relative;
}

.content-body :deep(h1) {
  font-size: 32px;
  border-bottom: 3px solid #667eea;
  padding-bottom: 12px;
}

.content-body :deep(h2) {
  font-size: 28px;
  border-left: 4px solid #667eea;
  padding-left: 16px;
}

.content-body :deep(h3) {
  font-size: 24px;
  color: #2c3e50;
}

.content-body :deep(h4) {
  font-size: 20px;
  color: #34495e;
}

.content-body :deep(p) {
  margin: 20px 0;
  line-height: 1.8;
  color: #2c3e50;
}

/* 图片样式 - 支持 md-preview 组件 */
.content-body :deep(img),
.content-body :deep(.md-preview img) {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  margin: 24px 0;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
  transition: all 0.3s ease;
}

.content-body :deep(img:hover),
.content-body :deep(.md-preview img:hover) {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
}

.content-body :deep(ul),
.content-body :deep(ol) {
  margin: 20px 0;
  padding-left: 28px;
}

.content-body :deep(li) {
  margin: 10px 0;
  line-height: 1.8;
  color: #2c3e50;
}

.content-body :deep(table) {
  width: 100%;
  border-collapse: collapse;
  margin: 24px 0;
  border: 1px solid #dee2e6;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.content-body :deep(th),
.content-body :deep(td) {
  padding: 16px 20px;
  text-align: left;
  border-bottom: 1px solid #dee2e6;
}

.content-body :deep(th) {
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  font-weight: 700;
  color: #1a1a1a;
  font-size: 14px;
}

.content-body :deep(tr:hover) {
  background: rgba(102, 126, 234, 0.05);
}

/* 左侧固定操作栏样式 */
.left-action-bar {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  background: #fff;
  border-radius: 8px;
  padding: 16px 0;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  gap: 16px;
  z-index: 1000;
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
}

.left-action-bar .action-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.left-action-bar .action-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px 8px;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 8px;
  margin: 0 8px;
  position: relative;
}

.left-action-bar .action-item:hover {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
  transform: translateY(-3px) scale(1.05);
}

.left-action-bar .action-item.active {
  color: #667eea;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.15) 0%, rgba(118, 75, 162, 0.15) 100%);
}

.left-action-bar .action-item .anticon {
  font-size: 20px;
  color: inherit;
  transition: all 0.3s ease;
}

.left-action-bar .action-item:hover .anticon {
  transform: scale(1.1);
}

.left-action-bar .action-item .count {
  font-size: 12px;
  color: inherit;
  font-weight: 600;
}

.left-action-bar .author-actions-sidebar {
  border-top: 1px solid #e9ecef;
  padding-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-left: 12px;
  padding-right: 12px;
}

.left-action-bar .author-actions-sidebar .ant-btn {
  border: none;
  box-shadow: none;
  padding: 6px 12px;
  height: auto;
  font-size: 13px;
  text-align: left;
  border-radius: 8px;
  transition: all 0.3s ease;
}

.left-action-bar .author-actions-sidebar .ant-btn:hover {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
  transform: translateX(4px);
}

/* 侧边栏样式 */
.article-sidebar {
  width: 320px;
  flex-shrink: 0;
  display: flex;
  position: sticky;
  top: 0px;
  align-self: flex-start;
  flex-direction: column;
}

/* 作者卡片 */
.author-card {
  background: #fff;
  border-radius: 8px;
  padding: 24px 20px;
  padding-bottom: 60px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
  margin-bottom: 24px;
  position: relative;
  overflow: hidden;
}

.author-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
}

.author-card-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 20px;
}

.author-card-avatar {
  color: #fff;
  box-shadow: 0 6px 16px rgba(102, 126, 234, 0.3);
  transition: all 0.3s ease;
  cursor: pointer;
}

.author-card-info {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: calc(100% - 64px);
}

.author-card-name {
  font-weight: 700;
  color: #1a1a1a;
  cursor: pointer;
  font-size: 18px;
  margin-bottom: 6px;
  transition: all 0.3s ease;
}

.author-card-stats {
  display: flex;
  gap: 6px;
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: #6c757d;
  font-weight: 500;
}

.author-card-stats .stat-item {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: #6c757d;
  font-weight: 500;
}

.author-card-stats .stat-item .anticon {
  font-size: 12px;
  /* 移除强制颜色设置，保持图标原有颜色 */
}

.author-card-meta {
  font-size: 14px;
  color: #6c757d;
  width: 100%;
  display: flex;
  justify-content: start;
  align-items: center;
  margin-bottom: 16px;
}

.author-card-meta .anticon {
  font-size: 12px;
  /* 移除强制颜色设置，保持图标原有颜色 */
}

.author-card-views {
  display: block;
  margin-left: 20px;
}

.author-card-views .anticon {
  margin-right: 6px;
}

.author-card-actions {
  margin-left: 64px;
  margin-top: 16px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.author-card-actions .ant-btn {
  border-radius: 25px;
  font-size: 13px;
  height: 32px;
  padding: 0 16px;
  font-weight: 600;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* 文章目录样式 */
.article-catalog {
  width: 320px;
  background: #fff;
  border-radius: 8px;
  border: 1px solid #e9ecef;
  padding: 20px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10px);
  position: sticky;
  top: 20px;
  align-self: flex-start;
}

.article-catalog::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, #f093fb 0%, #f5576c 100%);
}

.catalog-header {
  margin-bottom: 16px;
}

.catalog-header h4 {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  color: #1a1a1a;
  display: flex;
  align-items: center;
  gap: 8px;
}

.catalog-header .anticon {
  font-size: 20px;
  /* 保持目录图标的特殊颜色 */
  color: #f093fb;
}

.catalog-list {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  max-height: calc(100vh - 440px);
}

.catalog-item {
  padding: 8px 0;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 8px;
  position: relative;
  margin-bottom: 4px;
}

.catalog-item:hover {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
}

.catalog-text {
  font-size: 15px;
  color: #495057;
  line-height: 1.5;
  display: block;
  word-break: break-all;
  font-weight: 500;
  transition: all 0.3s ease;
}

.catalog-item:hover .catalog-text {
  color: #667eea;
  font-weight: 600;
}

/* 不同级别的标题缩进 */
.catalog-item.level-1 {
  padding-left: 0;
}

.catalog-item.level-2 {
  padding-left: 20px;
}

.catalog-item.level-3 {
  padding-left: 40px;
}

.catalog-item.level-4 {
  padding-left: 60px;
}

.catalog-item.level-5 {
  padding-left: 80px;
}

.catalog-item.level-6 {
  padding-left: 100px;
}

/* 滚动条样式 */
.catalog-list::-webkit-scrollbar {
  width: 6px;
}

.catalog-list::-webkit-scrollbar-track {
  background: #f8f9fa;
  border-radius: 3px;
}

.catalog-list::-webkit-scrollbar-thumb {
  background: linear-gradient(135deg, #d2d2d2 0%, #c5c5c5 100%);
  border-radius: 3px;
}

.catalog-list::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(135deg, #acb6e6 0%, #cebae2 100%);
}

.action-bar {
  position: fixed;
  top: 50%;
  right: 20px;
  transform: translateY(-50%);
  background: #fff;
  border-radius: 16px;
  padding: 16px 0;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  gap: 16px;
  z-index: 1000;
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
}

.action-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.action-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px 8px;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 8px;
  margin: 0 8px;
  position: relative;
}

.action-item:hover {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
  transform: translateY(-3px) scale(1.05);
}

.action-item.active {
  color: #667eea;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.15) 0%, rgba(118, 75, 162, 0.15) 100%);
}

.action-item .anticon {
  font-size: 20px;
  color: inherit;
  transition: all 0.3s ease;
}

.action-item:hover .anticon {
  transform: scale(1.1);
}

.action-item .count {
  font-size: 12px;
  color: inherit;
  font-weight: 600;
}

/* 文章底部操作区 */
.article-footer {
  border-top: 1px solid #f0f0f0;
  padding: 32px;
  background: linear-gradient(135deg, #fafbfc 0%, #f8f9fa 100%);
}

.action-buttons {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  flex-wrap: wrap;
}

.action-btn {
  min-width: 140px;
  height: 48px;
  border-radius: 24px;
  font-weight: 600;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  font-size: 15px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}

.action-btn.like-btn.active {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border: none;
  color: #fff;
  box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
}

.action-btn.favorite-btn.active {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  border: none;
  color: #fff;
  box-shadow: 0 8px 24px rgba(240, 147, 251, 0.3);
}

.action-btn.share-btn {
  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
  border: none;
  color: #fff;
  box-shadow: 0 8px 24px rgba(79, 172, 254, 0.3);
}

.action-btn:hover {
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
}

.author-actions {
  display: flex;
  gap: 16px;
  margin-left: 20px;
}

.author-actions-sidebar {
  border-top: 1px solid #e9ecef;
  padding-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-left: 12px;
  padding-right: 12px;
}

.author-actions-sidebar .ant-btn {
  border: none;
  box-shadow: none;
  padding: 6px 12px;
  height: auto;
  font-size: 13px;
  text-align: left;
  border-radius: 8px;
  transition: all 0.3s ease;
}

.author-actions-sidebar .ant-btn:hover {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
  transform: translateX(4px);
}

.comments-section {
  margin-top: 0;
  border-top: 1px solid #f0f0f0;
  padding: 40px 32px;
  background: #fff;
}

.comments-header {
  margin-bottom: 32px;
}

.comments-header h3 {
  font-size: 24px;
  font-weight: 700;
  color: #1a1a1a;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  position: relative;
}

.comments-header h3::before {
  content: '';
  width: 6px;
  height: 24px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 3px;
}

.comment-form {
  background: linear-gradient(135deg, #fafbfc 0%, #f8f9fa 100%);
  border-radius: 16px;
  padding: 24px;
  margin-bottom: 40px;
  border: 1px solid #e9ecef;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
}

.comment-form-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 20px;
}

.user-avatar {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  flex-shrink: 0;
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

.username {
  font-weight: 600;
  color: #1a1a1a;
  font-size: 16px;
}

.comment-textarea {
  margin-bottom: 16px;
}

.comment-textarea :deep(.ant-input) {
  border: 2px solid #e9ecef;
  border-radius: 8px;
  font-size: 15px;
  line-height: 1.6;
  padding: 16px;
  transition: all 0.3s ease;
  background: #fff;
}

.comment-textarea :deep(.ant-input:focus) {
  border-color: #667eea;
  box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
  transform: translateY(-1px);
}

.comment-form-actions {
  text-align: right;
}

.login-tip {
  margin-bottom: 40px;
}

.comment-item {
  display: flex;
  gap: 16px;
  margin-bottom: 32px;
  padding: 24px;
  background: linear-gradient(135deg, #fafbfc 0%, #f8f9fa 100%);
  border-radius: 16px;
  border: 1px solid #e9ecef;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.comment-content {
  flex: 1;
}

.comment-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.comment-author {
  font-weight: 700;
  color: #1a1a1a;
  font-size: 15px;
}

.comment-time {
  font-size: 14px;
  color: #6c757d;
  font-weight: 500;
}

.comment-text {
  color: #2c3e50;
  line-height: 1.7;
  margin-bottom: 18px;
  white-space: pre-wrap;
  font-size: 15px;
}

.comment-actions {
  display: flex;
  gap: 16px;
}

.comment-actions .ant-btn {
  border: none;
  box-shadow: none;
  padding: 6px 12px;
  height: auto;
  color: #6c757d;
  transition: all 0.3s ease;
  border-radius: 8px;
  font-weight: 500;
}

.comment-actions .ant-btn:hover {
  color: #667eea;
  background: rgba(102, 126, 234, 0.1);
  transform: translateY(-1px);
}

.comment-actions .ant-btn.liked {
  color: #667eea;
  background: rgba(102, 126, 234, 0.1);
}

.comment-actions .ant-btn.ant-btn-dangerous {
  color: #dc3545;
}

.comment-actions .ant-btn.ant-btn-dangerous:hover {
  color: #dc3545;
  background: rgba(220, 53, 69, 0.1);
}

.replies-list {
  margin-top: 20px;
  padding-left: 28px;
  border-left: 4px solid #667eea;
  background: rgba(102, 126, 234, 0.03);
  border-radius: 0 12px 12px 0;
  padding-top: 16px;
  padding-bottom: 12px;
}

.reply-item {
  display: flex;
  gap: 12px;
  margin-bottom: 20px;
  padding: 16px;
  background: #fff;
  border-radius: 8px;
  border: 1px solid #e9ecef;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
  transition: all 0.3s ease;
}

.reply-content {
  flex: 1;
}

.reply-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}

.reply-author {
  font-weight: 600;
  color: #1a1a1a;
  font-size: 14px;
}

.reply-time {
  font-size: 13px;
  color: #6c757d;
  font-weight: 500;
}

.reply-text {
  color: #2c3e50;
  line-height: 1.6;
  margin-bottom: 12px;
  font-size: 14px;
  white-space: pre-wrap;
}

.reply-actions {
  display: flex;
  gap: 12px;
}

.reply-actions .ant-btn {
  border: none;
  box-shadow: none;
  padding: 4px 8px;
  height: auto;
  color: #6c757d;
  font-size: 14px;
  transition: all 0.3s ease;
  border-radius: 6px;
  font-weight: 500;
}

.reply-actions .ant-btn:hover {
  color: #667eea;
  background: rgba(102, 126, 234, 0.1);
  transform: translateY(-1px);
}

.reply-actions .ant-btn.liked {
  color: #667eea;
  background: rgba(102, 126, 234, 0.1);
}

.reply-actions .ant-btn.ant-btn-dangerous {
  color: #dc3545;
}

.reply-actions .ant-btn.ant-btn-dangerous:hover {
  color: #dc3545;
  background: rgba(220, 53, 69, 0.1);
}

.reply-form {
  margin-top: 16px;
  padding: 20px;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  border-radius: 8px;
  border: 1px solid #dee2e6;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.reply-form-actions {
  text-align: right;
  margin-top: 16px;
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}

.load-more-comments {
  text-align: center;
  margin-top: 40px;
}

.load-more-comments .ant-btn {
  border-radius: 25px;
  height: 44px;
  padding: 0 32px;
  font-weight: 600;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border: none;
  color: #fff;
  box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
  transition: all 0.3s ease;
}

.load-more-comments .ant-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);
}

.no-comments {
  text-align: center;
  padding: 40px 0;
}

.article-not-found {
  text-align: center;
  padding: 60px 0;
}

/* 响应式设计 */
@media (max-width: 1024px) {
  .article-wrapper {
    flex-direction: column;
    gap: 0;
  }

  .article-main {
    order: 1;
  }

  .article-sidebar {
    order: 0;
    width: 100%;
    margin-bottom: 24px;
    position: static;
  }

  .author-card {
    width: 100%;
    margin-bottom: 20px;
  }

  .article-catalog {
    width: 100%;
    margin-bottom: 20px;
    max-height: 300px;
  }

  /* 左侧操作栏在平板端调整位置 */
  .left-action-bar {
    left: 10px;
  }

  .action-bar {
    position: static;
    flex-direction: row;
    justify-content: center;
    padding: 20px;
    margin-top: 20px;
  }

  .action-group {
    flex-direction: row;
    gap: 32px;
  }

  .author-actions-sidebar {
    border-top: none;
    border-left: 1px solid #e9ecef;
    padding-top: 0;
    padding-left: 32px;
    flex-direction: row;
    gap: 16px;
  }

  .article-footer {
    padding: 24px 20px;
  }

  .action-buttons {
    flex-direction: column;
    gap: 16px;
  }

  .action-btn {
    width: 100%;
    min-width: auto;
  }

  .author-actions {
    margin-left: 0;
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid #e9ecef;
    justify-content: center;
  }
}

@media (max-width: 768px) {
  .article-detail {
    padding: 16px 0;
  }

  .article-wrapper {
    padding: 0 16px;
  }

  .article-title {
    font-size: 28px;
  }

  .article-meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }

  .article-header {
    padding: 24px 20px;
  }

  .article-content {
    padding: 24px 20px;
  }

  .content-body {
    font-size: 15px;
  }

  .content-body :deep(h1) {
    font-size: 28px;
  }

  .content-body :deep(h2) {
    font-size: 24px;
  }

  .content-body :deep(h3) {
    font-size: 20px;
  }

  /* 移动端左侧操作栏调整 */
  .left-action-bar {
    left: 8px;
    padding: 12px 0;
  }

  .left-action-bar .action-item {
    padding: 8px 6px;
  }

  .left-action-bar .action-item .anticon {
    font-size: 18px;
  }

  .left-action-bar .action-item .count {
    font-size: 11px;
  }

  .action-bar {
    padding: 16px;
  }

  .action-group {
    gap: 24px;
  }

  .comments-section {
    padding: 24px 20px;
  }

  .comment-form {
    padding: 20px;
  }

  .comment-item {
    gap: 12px;
    padding: 20px;
  }

  .replies-list {
    padding-left: 20px;
  }

  .reply-item {
    padding: 12px;
  }

  .author-card {
    padding: 20px 16px;
  }

  .article-catalog {
    padding: 16px;
  }
}

@media (max-width: 480px) {
  .article-wrapper {
    padding: 0 12px;
  }

  .article-header {
    padding: 20px 16px;
  }

  .article-content {
    padding: 20px 16px;
  }

  .article-title {
    font-size: 24px;
  }

  /* 小屏幕左侧操作栏调整 */
  .left-action-bar {
    left: 4px;
    padding: 10px 0;
  }

  .left-action-bar .action-item {
    padding: 6px 4px;
  }

  .left-action-bar .action-item .anticon {
    font-size: 16px;
  }

  .left-action-bar .action-item .count {
    font-size: 10px;
  }

  .action-buttons {
    gap: 12px;
  }

  .action-btn {
    min-width: 120px;
    height: 44px;
    font-size: 14px;
  }

  .comments-section {
    padding: 20px 16px;
  }

  .comment-form {
    padding: 16px;
  }

  .comment-item {
    padding: 16px;
  }

  .reply-item {
    padding: 12px;
  }
}
</style>
